package kamikaze.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import kamikaze.utils.StringUtil;

import com.google.appengine.api.datastore.Key;

@Entity
public class User implements Serializable, HasKey {

	private static final long serialVersionUID = 489247354109866291L;

	public enum CardType {
		VISA, MASTERCARD
	};

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Key key;

	private String loginId;
	private String name;
	private String email;
	private String password;
	private String cardName;
	private CardType cardType;
	private String cardNumber;
	@Temporal(TemporalType.DATE)
	private Date expiredDate;
	private boolean suspended = false;
	private long suspensionPeriod;
	@Temporal(TemporalType.TIMESTAMP)
	private Date lastUpdateDate;

	public Key getKey() {
		return key;
	}

	public void setKey(Key key) {
		this.key = key;
	}

	public String getLoginId() {
		return loginId;
	}

	public void setLoginId(String loginId) {
		this.loginId = loginId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getCardName() {
		return cardName;
	}

	public void setCardName(String cardName) {
		this.cardName = cardName;
	}

	public CardType getCardType() {
		return cardType;
	}

	public void setCardType(CardType cardType) {
		this.cardType = cardType;
	}

	public String getCardNumber() {
		return cardNumber;
	}

	public String getMaskedCardNumber() {
		String firstPart = cardNumber.substring(0, cardNumber.length() - 4);
		String lastPart = cardNumber.substring(cardNumber.length() - 4);
		firstPart = firstPart.replaceAll("^[0-9]+$", "*");

		String masked = firstPart.concat(lastPart);
		return masked;
	}

	public void setCardNumber(String cardNumber) {
		this.cardNumber = cardNumber;
	}

	public Date getExpiredDate() {
		return expiredDate;
	}

	public void setExpiredDate(Date expiredDate) {
		this.expiredDate = expiredDate;
	}

	public boolean isSuspended() {

		boolean isInSuspensionPeriod = false;
		if (suspensionPeriod > 0L) {
			Date date = new Date();
			Date dateSuspensionPeriod = new Date(suspensionPeriod);
			if (date.before(dateSuspensionPeriod)) {
				isInSuspensionPeriod = true;
			}
		}

		return suspended || isInSuspensionPeriod;
	}

	public void setSuspended(boolean suspended) {
		this.suspended = suspended;
	}

	public Long getSuspensionPeriod() {
		return suspensionPeriod;
	}

	public void setSuspensionPeriod(Long suspensionPeriod) {
		this.suspensionPeriod = suspensionPeriod;
	}

	public Date getLastUpdateDate() {
		return lastUpdateDate;
	}

	public void setLastUpdateDate(Date lastUpdateDate) {
		this.lastUpdateDate = lastUpdateDate;
	}

	public List<String> validate() {
		List<String> errorMessages = new ArrayList<String>();

		if (loginId == null || loginId.isEmpty()) {
			errorMessages.add("Login ID cannot be empty");
		} else if (loginId.length() < 8 || loginId.length() > 16) {
			errorMessages
					.add("Login ID min 8 characters and max 16 characters.");
		} else if (!StringUtil.isAlphabetOnly(loginId)) {
			errorMessages.add("Login ID only alphabet accepted");
		}

		if (password == null || password.isEmpty()) {
			errorMessages.add("Password cannot be empty");
		} else if (password.length() < 8 || password.length() > 16) {
			errorMessages
					.add("Password min 8 characters and max 16 characters");
		} else if (!StringUtil.isAlphaNumeric(password)) {
			errorMessages.add("Password must be alphanumeric");
		}

		if (name == null || name.isEmpty()) {
			errorMessages.add("Name cannot be empty");
		} else if (name.length() > 100) {
			errorMessages.add("Name maximum 100 characters");
		}

		if (email == null || email.isEmpty()) {
			errorMessages.add("Email cannot be empty");
		} else if (!StringUtil.isEmailAddress(email)) {
			errorMessages.add("Invalid Email address");
		}

		if (cardName == null || cardName.isEmpty()) {
			errorMessages.add("Card Name cannot be empty");
		} else if (cardName.length() > 100) {
			errorMessages.add("Card Name maximum 100 characters.");
		}

		if (cardType == CardType.VISA && !StringUtil.isVisaCard(cardNumber)) {
			errorMessages.add("Invalid Credit Card No");
		} else if (cardType == CardType.MASTERCARD
				&& !StringUtil.isMasterCard(cardNumber)) {
			errorMessages.add("Invalid Credit Card No.");
		}

		if (expiredDate == null) {
			errorMessages.add("Card Expiry Date cannot be empty");
		} else {
			Date currentDate = new Date();
			if (currentDate.after(expiredDate)) {
				errorMessages.add("Invalid Card. Card has already expired.");
			}
		}

		return errorMessages;
	}

}
